using System;
using System.Collections;
using System.Collections.Specialized;

namespace Waymex.Buffers
{
	/// <summary>
	/// The StringFifo class implements a First In First Out (FIFO) buffer for strings.
	/// The class is thread safe. The property BufferStrings sets the maximum amount of 
	/// strings that may be placed in the buffer. If an attempt is made to exceed this amount
	/// and Exception is raised. The BufferStrings defaults to 1000.
	/// </summary>
	internal class StringFifo
	{
		StringCollection m_Buffer = new StringCollection();
		int m_BufferStrings = 1000;

		/// <summary>
		/// Constructor for the StringFifo class.
		/// </summary>
		internal StringFifo()
		{
			// Creates and initializes a new StringCollection.
			 
		}
		/// <summary>
		/// This method clears all the strings from the buffer.
		/// </summary>
		internal void Clear()
		{
			lock(m_Buffer.SyncRoot)
			{
				m_Buffer.Clear();
			}
		}
		/// <summary>
		/// This method adds a string to the buffer.
		/// </summary>
		/// <param name="StringData"></param>
		internal void Add(string StringData)
		{
			lock(m_Buffer.SyncRoot)
			{
				if( m_Buffer.Count < m_BufferStrings )
					m_Buffer.Add(StringData);
				else
					throw new BufferException(Strings.Buffers_BufferFull);
			}
		}
		/// <summary>
		/// This method returns the string that has been in the buffer the longest (FIFO).
		/// The string is removed from the buffer.
		/// </summary>
		/// <returns></returns>
		internal string Remove()
		{
			string data = null;

			if( this.Count > 0 )
			{
				lock(m_Buffer.SyncRoot)
				{
					data = m_Buffer[0];
					m_Buffer.RemoveAt(0);
				}
			}
			return data;
		}
		/// <summary>
		/// This method returns the string that has been in the buffer the longest (FIFO).
		/// The string is removed from the buffer. The Seconds represents the number of seconds
		/// the method will check for data in the buffer before returning.
		/// </summary>
		/// <returns></returns>
		internal string Remove(int Seconds)
		{
			string data = null;
			bool expired = false;

			//loop until WaitTime has expired
			double ticksNow = Timer();		
			
			while(!expired)
			{
				if( this.Count > 0 )
				{
					lock(m_Buffer.SyncRoot)
					{
						data = m_Buffer[0];
						m_Buffer.RemoveAt(0);
					}
					break;

				}
				if( Timer() > ticksNow + Seconds)
					expired = true;

			}
			return data;
		}

		/// <summary>
		/// Sets/Gets the maximum strings that can be stored in the buffer. Defaults to 1000.
		/// </summary>
		internal int BufferStrings
		{
			get
			{
				return m_BufferStrings;
			}
			set
			{
				m_BufferStrings = value;
			}
		}
		/// <summary>
		/// Returns the number of strings in the buffer.
		/// </summary>
		internal int Count
		{
			get
			{
				return m_Buffer.Count;
			}
		}
		/// <summary>
		/// Emulates the Visual Basic Timer() function.
		/// </summary>
		/// <returns></returns>
		private static double Timer() 
		{
			DateTime dtTimer;

			dtTimer = DateTime.Now;
			return (double) dtTimer.Ticks % 711573504 / 1e+007;
		}

	}
}
